package sf.dsl.example;

import sf.database.dialect.DBDialect;
import sf.database.jdbc.sql.SQLParameter;
import sf.spring.util.CollectionUtils;

import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;

public class CaseBuilder {

    public static class CaseField extends SimpleField {
        protected List<ICondition> conditions = new LinkedList<>();

        protected SimpleField simpleField;

        public CaseField(SimpleField field) {
            this.simpleField = field;
        }

        public CaseField when(Object value) {
            conditions.add(QPI.addCondition(" when "));
            conditions.add(QPI.add(value));
            return this;
        }

        public CaseField then(Object value) {
            conditions.add(QPI.addCondition(" then "));
            conditions.add(QPI.add(value));
            return this;
        }

        public CaseField otherwise(Object value) {
            conditions.add(QPI.addCondition(" else "));
            conditions.add(QPI.add(value));
            conditions.add(QPI.addCondition(" end "));
            return this;
        }

        @Override
        public void toConditionSql(StringBuilder sb, List<SQLParameter> list, AtomicBoolean useDefaultTableNameAlias, boolean useTablePrefix, DBDialect dialect) {
            sb.append(" (case ");
            if (simpleField != null) {
                simpleField.toConditionSql(sb, list, useDefaultTableNameAlias, useTablePrefix, dialect);
            }
            if (CollectionUtils.isNotEmpty(conditions)) {
                for (ICondition condition : conditions) {
                    condition.toSql(sb, list, useDefaultTableNameAlias, dialect);
                }
            }
            sb.append(')');
        }
    }

    public static class Case extends SimpleField {
        protected List<ICondition> conditionList = new LinkedList<>();

        public Case when(ICondition... conditions) {
            conditionList.add(QPI.addCondition(" when "));
            Collections.addAll(conditionList, conditions);
            return this;
        }

        public Case then(Object value) {
            conditionList.add(QPI.addCondition(" then "));
            conditionList.add(QPI.add(value));
            return this;
        }

        public Case otherwise(Object value) {
            conditionList.add(QPI.addCondition(" else "));
            conditionList.add(QPI.add(value));
            conditionList.add(QPI.addCondition(" end "));
            return this;
        }

        @Override
        public void toConditionSql(StringBuilder sb, List<SQLParameter> list, AtomicBoolean useDefaultTableNameAlias, boolean useTablePrefix, DBDialect dialect) {
            sb.append(" (case ");
            if (CollectionUtils.isNotEmpty(conditionList)) {
                for (ICondition condition : conditionList) {
                    condition.toSql(sb, list, useDefaultTableNameAlias, dialect);
                }
            }
            sb.append(')');
        }
    }

    public static CaseField CASE(SimpleField field) {
        return new CaseField(field);
    }

    public static Case CASE() {
        return new Case();
    }
}
